/***************************************************************************
 *	@file 		fetion_contact.h
 *	@Author 	baoyu0125@gmail.com
 *	@create		2011-7
 *	@version 	1.0.0
 *	@brief		definition of class Group and Contact
 *				class Group and Contact contain information of fetion buddy 
 *				group and contact, as well as Function object for searching
 *				operation.
 *	@modify		none
 ***************************************************************************/

#ifndef FETION_CONTACT_H
#define FETION_CONTACT_H

#include "fetion_user.h"

typedef enum {
	BUDDY_LIST_NOT_GROUPED 	= 0 ,
	BUDDY_LIST_STRANGER 	= -1 ,
	BUDDY_LIST_PGGROUP 		= -2
} BuddyListType;

class SQLiteStatement;
class SQLiteWrapper;

class Group
{
public:
	friend class currentUser;
	class equal_by_id 
	{
	public:
		equal_by_id(const int &id) : _id(id) {}
		bool operator() (const Group &group) 
		{
			return group.groupId == _id;
		}
	private:
		int _id;
	};

	Group() {};
	Group(const int gi, const std::string gn) : 
		groupId(gi), groupName(gn), dirty(0) {}

	int load_from_database(SQLiteStatement *stmt);
	bool save_to_database(SQLiteWrapper &sqlite);

private:
	int groupId;
	std::string groupName;
	int dirty;
};

class Contact : public fetionUser
{
public:
	friend class currentUser;
	friend class SipProcNotify;
	friend class BuddyApply;
	friend class Conversation;
	
	class equal_by_userid 
	{
	public:
		equal_by_userid(const std::string &userid) : _userid(userid) {}
		bool operator() (const Contact &contact) 
		{
			return contact.userId == _userid;
		}
	private:
		std::string _userid;
	};

	class equal_by_sipuri 
	{
	public:
		equal_by_sipuri(const std::string &sip_uri) : _sipuri(sip_uri) {}
		bool operator() (const Contact &contact) 
		{
			return contact.sipuri == _sipuri;
		}
	private:
		std::string _sipuri;
	};
	
	class equal_by_groupid 
	{
	public:
		equal_by_groupid(const int group_id) : _groupid(group_id) {}
		bool operator() (const Contact &contact) 
		{
			return contact.groupid == _groupid;
		}
	private:
		int _groupid;
	};

	class equal_by_contact_string
	{
	public:
		equal_by_contact_string(const std::string ContactStr) 
			: _str(ContactStr) {}
		bool operator() (const Contact &contact);
	private:
		std::string _str;
	};
	
	bool operator< (Contact &contact);
	int load_from_database(SQLiteStatement *stmt);
	bool save_to_database(SQLiteWrapper &sqlite);
	
	int parse_contact_from_presence_p(xmlpp::Element *elem);
	int parse_contact_from_presence_pr(xmlpp::Element *elem);
	int parse_from_sipc(xmlpp::Element *elem);
	int parse_from_get_info_response(xmlpp::Element *elem);

//	int get_information_by_no(const std::string &no);
	static int generate_get_info_body(std::string &body, const std::string &no);
	void print_information();
	
	void clear();
	std::string get_contact_name()
	{
		if(localname.empty()) {
			return nickname;
		}
		else {
			return localname;
		}
	}

private:
	unsigned int index;					/* contact index in current user contact list		*/
	std::string localname;				/* name set by yourself				  				*/
	std::string devicetype;				/* user's client type , like PC and J2ME,etc		*/
	std::string portraitCrc;			/* a number generated by crc algorithm 				*/
	std::string birthday;				/* user's bitrhday									*/
	int identity;						/* whethere to show mobileno to this user   		*/
	int scoreLevel;						/* user's score level,unused now					*/
	int serviceStatus;					/* basic service status 								*/
	int carrierStatus;
	int relationStatus;
	std::string carrier;
	int groupid;						/* buddylist id										*/
	int imageChanged;					/* whether user's portrait has changed				*/
	int dirty;                          /* whether the contact just read from the server is
										   newer than that int the local disk */
};

/*class ContactList
{
public:
	ContactList() : 
		localContactCount(0), contactCount(0), localGroupCount(0), groupCount(0)
	{
		clist.clear();
		glist.clear();
	}
	int parse_contact_list(xmlpp::Node *pNode);
public:
	std::list<Contact> clist;
	std::list<Group> glist;
	int localContactCount, contactCount;
	int localGroupCount, groupCount;
};
*/
class BuddyApply
{
public:
	class SingleApply
	{
	public:
		
		std::string sipuri;
		std::string userid;
		std::string desc;
		int phraseId;
		int applyId;
	};
	void addApply(SingleApply &app) 
	{
		app.applyId = app_.size();
		app_.push_back(app);
	}
	void prompt();
	std::string generate_handle_body(const int index, const bool result/*, Contact &contact*/);
	bool remove_apply(const std::string &user_id, std::string &name);
	int size() { return app_.size(); }
private:
	std::vector<SingleApply> app_;
};

#endif
